deploy: Write bootloader config even if just kernel arguments changed
authorColin Walters <walters@verbum.org>
Wed, 15 Jan 2014 13:46:05 +0000 (08:46 -0500)
committerColin Walters <walters@verbum.org>
Wed, 15 Jan 2014 14:19:32 +0000 (09:19 -0500)
The official way to add bootloader arguments to the current deployment
is to redeploy with --karg.  However, doing so tripped up an
optimization made inside the deployment code to just swap the
bootlinks if we're keeping the same "bootcsum".

Change this optimization to look at the pair of (bootcsum, options).

Makefile-tests.am
src/libostree/ostree-sysroot-deploy.c
tests/test-admin-deploy-karg.sh [new file with mode: 0644]

index c51b1144159a8a1ee3e6707effde45d0d972f102..87ae8d0514010427ec11daf17824c94bff79dbef 100644 (file)
@@ -34,6 +34,7 @@ testfiles = test-basic \
        test-gpg-signed-commit \
        test-admin-deploy-1 \
        test-admin-deploy-2 \
+       test-admin-deploy-karg \
        test-admin-deploy-etcmerge-cornercases \
        test-admin-deploy-uboot \
        test-setuid \
index b14b2b715eed2e01b0f0c47a9ba40e5e4acd7946..749a375a69adb3e9dc2eedeed9c7be7218a1412f 100644 (file)
@@ -737,8 +737,7 @@ swap_bootloader (OstreeSysroot  *sysroot,
 }
 
 static GHashTable *
-bootcsum_counts_for_deployment_list (GPtrArray   *deployments,
-                                     gboolean     set_bootserial)
+assign_bootserials (GPtrArray   *deployments)
 {
   guint i;
   GHashTable *ret = 
@@ -751,10 +750,47 @@ bootcsum_counts_for_deployment_list (GPtrArray   *deployments,
       guint count;
 
       count = GPOINTER_TO_UINT (g_hash_table_lookup (ret, bootcsum));
-      g_hash_table_replace (ret, (char*)bootcsum, GUINT_TO_POINTER (count + 1));
+      g_hash_table_replace (ret, (char*) bootcsum,
+                            GUINT_TO_POINTER (count + 1));
 
-      if (set_bootserial)
-        ostree_deployment_set_bootserial (deployment, count);
+      ostree_deployment_set_bootserial (deployment, count);
+    }
+  return ret;
+}
+
+static GHashTable *
+bootconfig_counts_for_deployment_list (GPtrArray   *deployments)
+{
+  guint i;
+  GHashTable *ret = 
+    g_hash_table_new_full (g_str_hash, g_str_equal, NULL, NULL);
+
+  for (i = 0; i < deployments->len; i++)
+    {
+      OstreeDeployment *deployment = deployments->pdata[i];
+      const char *bootcsum = ostree_deployment_get_bootcsum (deployment);
+      OstreeBootconfigParser *bootconfig = ostree_deployment_get_bootconfig (deployment);
+      const char *boot_options = ostree_bootconfig_parser_get (bootconfig, "options");
+      GChecksum *bootconfig_checksum = g_checksum_new (G_CHECKSUM_SHA256);
+      const char *bootconfig_checksum_str;
+      __attribute__((cleanup(_ostree_ordered_hash_cleanup))) OstreeOrderedHash *ohash = NULL;
+      gs_free char *boot_options_without_ostree = NULL;
+      guint count;
+      
+      /* We checksum the kernel arguments *except* ostree= */
+      ohash = _ostree_sysroot_parse_kernel_args (boot_options);
+      _ostree_ordered_hash_replace_key (ohash, "ostree", "");
+      boot_options_without_ostree = _ostree_sysroot_kernel_arg_string_serialize (ohash);
+
+      g_checksum_update (bootconfig_checksum, (guint8*)bootcsum, strlen (bootcsum));
+      g_checksum_update (bootconfig_checksum, (guint8*)boot_options_without_ostree,
+                         strlen (boot_options_without_ostree));
+
+      bootconfig_checksum_str = g_checksum_get_string (bootconfig_checksum);
+
+      count = GPOINTER_TO_UINT (g_hash_table_lookup (ret, bootconfig_checksum_str));
+      g_hash_table_replace (ret, g_strdup (bootconfig_checksum_str),
+                            GUINT_TO_POINTER (count + 1));
     }
   return ret;
 }
@@ -821,19 +857,17 @@ ostree_sysroot_write_deployments (OstreeSysroot     *self,
   guint i;
   gboolean requires_new_bootversion = FALSE;
   gboolean found_booted_deployment = FALSE;
-  gs_unref_hashtable GHashTable *new_bootcsum_to_count = NULL;
 
   g_assert (self->loaded);
 
-  /* Calculate the total number of deployments per bootcsums; while we
-   * are doing this, assign a bootserial to each new deployment.
+  /* Assign a bootserial to each new deployment.
    */
-  new_bootcsum_to_count = bootcsum_counts_for_deployment_list (new_deployments, TRUE);
+  assign_bootserials (new_deployments);
 
   /* Determine whether or not we need to touch the bootloader
-   * configuration.  If we have an equal number of deployments and
-   * more strongly an equal number of deployments per bootcsum, then
-   * we can just swap the subbootversion bootlinks.
+   * configuration.  If we have an equal number of deployments with
+   * matching bootloader configuration, then we can just swap the
+   * subbootversion bootlinks.
    */
   if (new_deployments->len != self->deployments->len)
     requires_new_bootversion = TRUE;
@@ -841,14 +875,16 @@ ostree_sysroot_write_deployments (OstreeSysroot     *self,
     {
       GHashTableIter hashiter;
       gpointer hkey, hvalue;
-      gs_unref_hashtable GHashTable *orig_bootcsum_to_count
-        = bootcsum_counts_for_deployment_list (self->deployments, FALSE);
+      gs_unref_hashtable GHashTable *new_bootconfig_to_count = 
+        bootconfig_counts_for_deployment_list (new_deployments);
+      gs_unref_hashtable GHashTable *orig_bootconfig_to_count
+        = bootconfig_counts_for_deployment_list (self->deployments);
 
-      g_hash_table_iter_init (&hashiter, orig_bootcsum_to_count);
+      g_hash_table_iter_init (&hashiter, orig_bootconfig_to_count);
       while (g_hash_table_iter_next (&hashiter, &hkey, &hvalue))
         {
           guint orig_count = GPOINTER_TO_UINT (hvalue);
-          gpointer new_countp = g_hash_table_lookup (new_bootcsum_to_count, hkey);
+          gpointer new_countp = g_hash_table_lookup (new_bootconfig_to_count, hkey);
           guint new_count = GPOINTER_TO_UINT (new_countp);
 
           if (orig_count != new_count)
diff --git a/tests/test-admin-deploy-karg.sh b/tests/test-admin-deploy-karg.sh
new file mode 100644 (file)
index 0000000..1f0b9c7
--- /dev/null
@@ -0,0 +1,46 @@
+#!/bin/bash
+#
+# Copyright (C) 2011 Colin Walters <walters@verbum.org>
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2 of the License, or (at your option) any later version.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the
+# Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+# Boston, MA 02111-1307, USA.
+
+set -e
+
+. $(dirname $0)/libtest.sh
+
+echo "1..1"
+
+setup_os_repository "archive-z2" "syslinux"
+
+echo "ok setup"
+
+echo "1..1"
+
+ostree --repo=sysroot/ostree/repo pull-local --remote=testos testos-repo testos/buildmaster/x86_64-runtime
+rev=$(ostree --repo=sysroot/ostree/repo rev-parse testos/buildmaster/x86_64-runtime)
+export rev
+# This initial deployment gets kicked off with some kernel arguments 
+ostree admin --sysroot=sysroot deploy --karg=root=LABEL=MOO --karg=quiet --os=testos testos:testos/buildmaster/x86_64-runtime
+ostree admin --sysroot=sysroot deploy --karg=FOO=BAR --os=testos testos:testos/buildmaster/x86_64-runtime
+ostree admin --sysroot=sysroot deploy --karg=TESTARG=TESTVALUE --os=testos testos:testos/buildmaster/x86_64-runtime
+assert_file_has_content sysroot/boot/loader/entries/ostree-testos-1.conf 'options.*FOO=BAR'
+assert_file_has_content sysroot/boot/loader/entries/ostree-testos-0.conf 'options.*FOO=BAR'
+assert_file_has_content sysroot/boot/loader/entries/ostree-testos-0.conf 'options.*TESTARG=TESTVALUE'
+ostree admin --sysroot=sysroot deploy --karg=ANOTHERARG=ANOTHERVALUE --os=testos testos:testos/buildmaster/x86_64-runtime
+assert_file_has_content sysroot/boot/loader/entries/ostree-testos-0.conf 'options.*TESTARG=TESTVALUE'
+assert_file_has_content sysroot/boot/loader/entries/ostree-testos-0.conf 'options.*ANOTHERARG=ANOTHERVALUE'
+
+echo "ok deploy with --karg, but same config"